package org.example.promise;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 类描述：Promise实现
 * <br>
 *
 * @author ZS
 * @version 1.0
 * @date 2020/12/29
 **/
public class Promise<V> extends PromiseSupport<V> {
    // 要履行的动作
    private Runnable fulfillmentAction;
    // 动作执行过程中异常的处理
    private Consumer<? super Throwable> exceptionHandler;

    public Promise() {
    }

    @Override
    protected void fulfill(V value) {
        super.fulfill(value);
        // 拦截器，进行后续处理
        postFulfillment();
    }

    @Override
    protected void fulfillExceptionally(Exception exception) {
        super.fulfillExceptionally(exception);
        // 针对异常的处理
        handlerException();
        // 执行后续处理
        postFulfillment();
    }

    /**
     * 处理任务执行过程中产生的异常
     */
    private void handlerException() {
        if (exception == null) {
            return;
        }
        exceptionHandler.accept(exception);
    }

    /**
     * 任务执行完毕后需要执行的动作
     */
    private void postFulfillment() {
        if (null == fulfillmentAction) {
            return;
        }
        fulfillmentAction.run();
    }


    /**
     * 异步任务执行
     *
     * @param task     待执行的任务
     * @param executor 执行器
     * @return
     */
    public Promise<V> fulfillInAsync(final Callable<V> task, Executor executor) {
        executor.execute(() -> {
            try {
                // 执行任务并将返回值回写
                fulfill(task.call());
            } catch (Exception e) {
                // 执行任务产生异常，将异常回写
                fulfillExceptionally(e);
            }
        });
        return this;
    }

    /**
     * 任务执行完后对返回值进行处理
     *
     * @param action
     * @return
     */
    public Promise<Void> thenAccept(Consumer<? super V> action) {
        Promise<Void> dest = new Promise<>();
        fulfillmentAction = new ConsumerAction(this, dest, action);
        return dest;
    }

    /**
     * 任务执行过程中异常的处理
     *
     * @param exceptionHandler
     * @return
     */
    public Promise<V> onError(Consumer<? super Throwable> exceptionHandler) {
        this.exceptionHandler = exceptionHandler;
        return this;
    }

    /**
     * 将上一个Promise的处理结果传递给下一个Promise
     *
     * @param function
     * @param <T>
     * @return
     */
    public <T> Promise<T> thenApply(Function<? super V, T> function) {
        Promise<T> dest = new Promise<>();
        fulfillmentAction = new TransferAction<T>(this, dest, function);
        return dest;
    }

    private class ConsumerAction implements Runnable {

        private final Promise<V> src;
        private final Promise<Void> dest;
        private final Consumer<? super V> action;

        public ConsumerAction(Promise<V> src, Promise<Void> dest, Consumer<? super V> action) {
            this.src = src;
            this.dest = dest;
            this.action = action;
        }

        @Override
        public void run() {
            try {
                // 异步获取返回值
                action.accept(src.get());
                // 将空值回写
                dest.fulfill(null);
            } catch (Throwable t) {
                // 异常
                dest.fulfillExceptionally((Exception) t.getCause());
            }
        }
    }

    private class TransferAction<T> implements Runnable {

        private final Promise<V> src;
        private final Promise<T> dest;
        private final Function<? super V, T> func;

        public TransferAction(Promise<V> src, Promise<T> dest, Function<? super V, T> func) {
            this.src = src;
            this.dest = dest;
            this.func = func;
        }

        @Override
        public void run() {
            try {
                dest.fulfill(func.apply(src.get()));
            } catch (Throwable t) {
                dest.fulfillExceptionally((Exception) t.getCause());
            }
        }
    }
}
